#include "garmin_tables.h"
#include "inifile.h"
+#include <QtCore/QXmlStreamWriter>
+
#define MYNAME "garmin_fs"
#define GARMIN_GPX_EXT_REFERENCE \
/* GPX - out */
void
-garmin_fs_xml_fprint(gbfile* ofd, const waypoint* waypt)
+garmin_fs_xml_fprint(gbfile* ofd, const waypoint* waypt,
+ QXmlStreamWriter& writer)
{
const char* phone, *addr;
garmin_fs_t* gmsd = GMSD_FIND(waypt);
WAYPT_HAS(waypt, temperature) ||
gmsd->flags.display) {
int space = 1;
-
+#if OLDGPX
gbfprintf(ofd, "%*s<extensions>\n", space++ * 2, "");
gbfprintf(ofd, "%*s<gpxx:WaypointExtension %s\">\n", space++ * 2, "", GARMIN_GPX_EXT_REFERENCE);
+#else
+ writer.writeStartElement("extensions");
+ writer.writeStartElement("gpxx:WaypointExtension");
+ writer.writeNamespace("http://www.garmin.com/xmlschemas/GpxExtensions/v3",
+ "gpxx");
+ writer.writeNamespace("http://www.w3.org/2001/XMLSchema-instance",
+ "xsi");
+ writer.writeAttribute("xsi:schemaLocation",
+ "http://www.garmin.com/xmlschemas/GpxExtensions/v3 "
+ "http://www.garmin.com/xmlschemas/GpxExtensions/v3/GpxExtensionsv3.xsd");
+// "http://www.garmin.com/xmlschemas/GpxExtensions/v3/GpxExtensionsv3.xsd"
+// "xmlns:gpxx=\"" \
+// "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " \
+// "xsi:schemaLocation=\"http://www.garmin.com/xmlschemas/GpxExtensions/v3 " \
+// "http://www.garmin.com/xmlschemas/GpxExtensions/v3/GpxExtensionsv3.xsd"
+// writer.writeEndElement();
+#endif
if WAYPT_HAS(waypt, proximity) {
gbfprintf(ofd, "%*s<gpxx:Proximity>%.6f</gpxx:Proximity>\n", space * 2, "", waypt->proximity);
}
cx = "SymbolAndName";
break;
}
+#if OLDGPX
gbfprintf(ofd, "%*s<gpxx:DisplayMode>%s</gpxx:DisplayMode>\n", space * 2, "", cx);
+#else
+ writer.writeTextElement("gpxx:DisplayMode", cx);
+#endif
}
if (gmsd->flags.category && gmsd->category) {
int i;
}
if (*addr) {
char* str, *tmp;
+#if OLDGPX
gbfprintf(ofd, "%*s<gpxx:Address>\n", space++ * 2, "");
+#else
+ writer.writeStartElement("gpxx:Address");
+#endif
if ((str = GMSD_GET(addr, NULL))) {
+#if OLDGPX
tmp = xml_entitize(str);
gbfprintf(ofd, "%*s<gpxx:StreetAddress>%s</gpxx:StreetAddress>\n", space * 2, "", tmp);
xfree(tmp);
+#else
+ writer.writeTextElement("gpxx:StreetAddress", str);
+#endif
}
if ((str = GMSD_GET(city, NULL))) {
+#if OLDGPX
tmp = xml_entitize(str);
gbfprintf(ofd, "%*s<gpxx:City>%s</gpxx:City>\n", space * 2, "", tmp);
xfree(tmp);
+#else
+ writer.writeTextElement("gpxx:City", str);
+#endif
}
if ((str = GMSD_GET(state, NULL))) {
+#if OLDGPX
tmp = xml_entitize(str);
gbfprintf(ofd, "%*s<gpxx:State>%s</gpxx:State>\n", space * 2, "", tmp);
xfree(tmp);
+#else
+ writer.writeTextElement("gpxx:State", str);
+#endif
}
if ((str = GMSD_GET(country, NULL))) {
+#if OLDGPX
tmp = xml_entitize(str);
gbfprintf(ofd, "%*s<gpxx:Country>%s</gpxx:Country>\n", space * 2, "", tmp);
+#else
+ writer.writeTextElement("gpxx:Country", str);
+#endif
xfree(tmp);
}
if ((str = GMSD_GET(postal_code, NULL))) {
+#if OLDGPX
tmp = xml_entitize(str);
gbfprintf(ofd, "%*s<gpxx:PostalCode>%s</gpxx:PostalCode>\n", space * 2, "", tmp);
xfree(tmp);
+#else
+ writer.writeTextElement("gpxx:PostalCode", str);
+#endif
}
-
+#if OLDGPX
gbfprintf(ofd, "%*s</gpxx:Address>\n", --space * 2, "");
+#else
+ writer.writeEndElement(); // /gpxx::Address
+#endif
}
if (*phone) {
+#if OLDGPX
char* tmp = xml_entitize(phone);
gbfprintf(ofd, "%*s<gpxx:PhoneNumber>%s</gpxx:PhoneNumber>\n", space * 2, "", tmp);
xfree(tmp);
+#else
+ writer.writeTextElement("gpxx:PhoneNumber", phone);
+#endif
}
+#if OLDGPX
gbfprintf(ofd, "%*s</gpxx:WaypointExtension>\n", --space * 2, "");
gbfprintf(ofd, "%*s</extensions>\n", --space * 2, "");
+#else
+ writer.writeEndElement(); // /gpxx::WaypointExtension
+ writer.writeEndElement(); // /extensions.
+#endif
}
}
-#define OLD 1 // Crutch while bringing up new XML writer
/*
Access GPX data files.
static XML_Parser psr;
#endif
#include <QtCore/QXmlStreamWriter>
+#include <QtCore/QRegExp>
#include <QtCore/QDebug>
-#include <QtCore/QTextCodec>
+//#include <QtCore/QTextCodec>
static xml_tag* cur_tag;
if (!gpx_global || QUEUE_EMPTY(&ge->queue)) {
return;
}
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "<%s>", tag);
#else
writer.writeStartElement(tag);
#endif
QUEUE_FOR_EACH(&ge->queue, elem, tmp) {
gep = BASE_STRUCT(elem, gpx_global_entry, queue);
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "%s", gep->tagdata);
#else
writer.writeCharacters(gep->tagdata);
}
gbfprintf(ofd, " ");
}
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "</%s>\n", tag);
#else
writer.writeEndElement();
static void
gpx_wr_deinit(void)
{
-#if OLD
+#if OLDGPX
gbfclose(ofd);
#else
writer.writeEndDocument();
// for now, in the early days, just to keep things as we've always done it.
ostring.replace("'", "'");
+ // TODO: The old writer would more aggressively protect you from control
+ // character nonsense. The control-Z (032)is the only thing that appears in
+ // our test suite, but let's toss things we know aren't allowed in GPX.
+ // Let's just carpet-bomb the whole range for now. I have a feeling we'll
+ // revisit this in time...
+ ostring.replace(QRegExp("[\014-\032]"), " ");
+
gbfputs(ostring, ofd);
gbfclose(ofd);
ofd = NULL;
fprint_tag_and_attrs(const char* prefix, const char* suffix, xml_tag* tag)
{
char** pa;
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "%s%s", prefix, tag->tagname);
#endif
pa = tag->attributes;
if (pa) {
while (*pa) {
-#if OLD
+#if OLDGPX
gbfprintf(ofd, " %s=\"%s\"", pa[0], pa[1]);
pa += 2;
#else
#endif
}
}
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "%s", suffix);
#else
// writer.writeEndElement();
fprint_tag_and_attrs("<", ">", tag);
if (tag->cdata) {
-#if OLD
+#if OLDGPX
char* tmp_ent;
tmp_ent = xml_entitize(tag->cdata);
gbfprintf(ofd, "%s", tmp_ent);
xml_write_time(ofd, wpt->gc_data->exported, 0,
"groundspeak:exported");
}
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "</%s>\n", tag->tagname);
#else
writer.writeEndElement();
return;
}
-#if OLD
+#if OLDGPX
char* tmp_ent;
if (gpx_wversion_num > 10) {
url_link* tail;
writer.writeAttribute("href", tail->url);
}
if(tail->url_link_text && tail->url_link_text[0]) {
- writer.writeAttribute("text", tail->url_link_text);
+ writer.writeTextElement("text", tail->url_link_text);
}
+ // FIXME This is to force empty links to not be self-closing. This is
+ // lame, but it's for compatibilty with our old writer to minimize thrash
+ // on the Qt transition.
+ writer.writeCharacters("\n");
writer.writeEndElement();
}
return;
default:
break;
}
-#if OLD
+#if OLDGPX
if (fix) {
gbfprintf(ofd, "%s<fix>%s</fix>\n", indent, fix);
}
gpx_write_common_position(const waypoint* waypointp, const char* indent)
{
if (waypointp->altitude != unknown_alt) {
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "%s<ele>%f</ele>\n",
indent, waypointp->altitude);
#else
#endif
}
if (waypointp->creation_time) {
-#if OLD
+#if OLDGPX
gbfprintf(ofd, indent);
xml_write_time(ofd, waypointp->creation_time, waypointp->microseconds, "time");
#else
char time_string[64];
+ // FIXME: Eventually use creation_time.toString()
xml_fill_in_time(time_string, waypointp->creation_time, waypointp->microseconds, XML_LONG_TIME);
if (time_string[0]) {
writer.writeTextElement("time", time_string);
{
if (((opt_humminbirdext || opt_garminext) && (waypointp->depth != 0 || waypointp->temperature != 0))
|| (opt_garminext && (waypointp->heartrate != 0 || waypointp->cadence != 0))) {
+#if OLDGPX
gbfprintf(ofd, "%s<extensions>\n", indent);
if (waypointp->depth != 0) {
if (opt_humminbirdext)
gbfprintf(ofd, "%s </gpxtpx:TrackPointExtension>\n", indent);
}
gbfprintf(ofd, "%s</extensions>\n", indent);
+#else
+ writer.writeStartElement("extensions");
+ if (waypointp->depth != 0) {
+ if (opt_humminbirdext) {
+// gbfprintf(ofd, "%s <h:depth>%f</h:depth>\n",
+// indent, waypointp->depth*100.0);
+writer.writeTextElement("h:depth", QString::number(waypointp->depth * 100.0));
+ }
+ if (opt_garminext) {
+#if OLDGPX
+ gbfprintf(ofd, "%s <gpxx:Depth>%f</gpxx:Depth>\n",
+ indent, waypointp->depth);
+#else
+writer.writeTextElement("gpxx", "Depth", QString::number(waypointp->depth));
+#endif
+ }
+ }
+ if (waypointp->temperature != 0) {
+ if (opt_humminbirdext)
+ gbfprintf(ofd, "%s <h:temperature>%f</h:temperature>\n",
+ indent, waypointp->temperature);
+ if (opt_garminext)
+ gbfprintf(ofd, "%s <gpxx:Temperature>%f</gpxx:Temperature>\n",
+ indent, waypointp->temperature);
+ }
+ if (opt_garminext && (waypointp->heartrate != 0 || waypointp->cadence != 0)) {
+ gbfprintf(ofd, "%s <gpxtpx:TrackPointExtension>\n", indent);
+ if (waypointp->heartrate != 0)
+ gbfprintf(ofd, "%s <gpxtpx:hr>%u</gpxtpx:hr>\n",
+ indent, waypointp->heartrate);
+ if (waypointp->cadence != 0)
+ gbfprintf(ofd, "%s <gpxtpx:cad>%u</gpxtpx:cad>\n",
+ indent, waypointp->cadence);
+ gbfprintf(ofd, "%s </gpxtpx:TrackPointExtension>\n", indent);
+ }
+ writer.writeEndElement(); // "extensions"
+#endif
}
}
gpx_write_common_description(const waypoint* waypointp, const char* indent,
const char* oname)
{
-#if OLD
+#if OLDGPX
write_optional_xml_entity(ofd, indent, "name", oname);
write_optional_xml_entity(ofd, indent, "cmt", waypointp->description);
if (waypointp->notes && waypointp->notes[0]) {
const char* oname;
fs_xml* fs_gpx;
garmin_fs_t* gmsd; /* gARmIN sPECIAL dATA */
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "<wpt lat=\"" FLT_FMT "\" lon=\"" FLT_FMT "\">\n",
waypointp->latitude,
waypointp->longitude);
}
if (gmsd && (gpx_wversion_num > 10)) {
/* MapSource doesn't accepts extensions from 1.0 */
- garmin_fs_xml_fprint(ofd, waypointp);
+ garmin_fs_xml_fprint(ofd, waypointp, writer);
}
gpx_write_common_extensions(waypointp, " ");
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "</wpt>\n");
#else
writer.writeEndElement();
{
fs_xml* fs_gpx;
current_trk_head = rte;
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "<trk>\n");
write_optional_xml_entity(ofd, " ", "name", rte->rte_name);
write_optional_xml_entity(ofd, " ", "desc", rte->rte_desc);
if (waypointp->wpt_flags.new_trkseg) {
if (!first_in_trk) {
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "</trkseg>\n");
#else
writer.writeEndElement();
#endif
}
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "<trkseg>\n");
#else
writer.writeStartElement("trkseg");
#endif
}
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "<trkpt lat=\"" FLT_FMT_T "\" lon=\"" FLT_FMT_T "\">\n",
waypointp->latitude,
waypointp->longitude);
/* These were accidentally removed from 1.1 */
if (gpx_wversion_num == 10) {
if WAYPT_HAS(waypointp, course) {
-#if OLD
+#if OLDGPX
gbfprintf(ofd, " <course>%f</course>\n",
waypointp->course);
#else
#endif
}
if WAYPT_HAS(waypointp, speed) {
-#if OLD
+#if OLDGPX
gbfprintf(ofd, " <speed>%f</speed>\n",
waypointp->speed);
#else
}
gpx_write_common_extensions(waypointp, " ");
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "</trkpt>\n");
#else
writer.writeEndElement();
gpx_track_tlr(const route_head* rte)
{
if (!QUEUE_EMPTY(¤t_trk_head->waypoint_list)) {
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "</trkseg>\n");
#else
writer.writeEndElement();
#endif
}
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "</trk>\n");
#else
// FIXME This is to force empty tracks to not be self-closing. This is
gpx_route_hdr(const route_head* rte)
{
fs_xml* fs_gpx;
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "<rte>\n");
#else
writer.writeStartElement("rte");
#endif
-#if OLD
+#if OLDGPX
write_optional_xml_entity(ofd, " ", "name", rte->rte_name);
write_optional_xml_entity(ofd, " ", "desc", rte->rte_desc);
#else
- if (rte->rte_name) {
+ if (rte->rte_name && rte->rte_name[0]) {
writer.writeTextElement("name", rte->rte_name);
}
- if (rte->rte_desc) {
+ if (rte->rte_desc && rte->rte_desc[0]) {
writer.writeTextElement("desc", rte->rte_desc);
}
#endif
if (rte->rte_num) {
-#if OLD
+#if OLDGPX
gbfprintf(ofd, " <number>%d</number>\n", rte->rte_num);
#else
writer.writeTextElement("number", QString::number(rte->rte_num));
{
const char* oname;
fs_xml* fs_gpx;
-#if OLD
+#if OLDGPX
gbfprintf(ofd, " <rtept lat=\"" FLT_FMT_R "\" lon=\"" FLT_FMT_R "\">\n",
waypointp->latitude,
waypointp->longitude);
}
gpx_write_common_extensions(waypointp, " ");
-#if OLD
+#if OLDGPX
gbfprintf(ofd, " </rtept>\n");
#else
- // FIXME This is to force empty tracks to not be self-closing. This is
- // lame, but it's for compatibilty with our old writer to minimize thrash
- // on the Qt transition.
- writer.writeCharacters("\n");
writer.writeEndElement();
#endif
}
static void
gpx_route_tlr(const route_head* rte)
{
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "</rte>\n");
#else
+ // FIXME This is to force empty tracks to not be self-closing. This is
+ // lame, but it's for compatibilty with our old writer to minimize thrash
+ // on the Qt transition.
+ writer.writeCharacters("\n");
writer.writeEndElement(); // Close rte tag.
#endif
}
track_disp_all(NULL, NULL, gpx_waypt_bound_calc);
if (waypt_bounds_valid(&all_bounds)) {
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "<bounds minlat=\"%0.9f\" minlon=\"%0.9f\" "
"maxlat=\"%0.9f\" maxlon=\"%0.9f\"/>\n",
all_bounds.min_lat, all_bounds.min_lon,
}
now = current_time();
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", global_opts.charset_name);
gbfprintf(ofd, "<gpx\n version=\"%s\"\n", gpx_wversion);
gbfprintf(ofd, " creator=\"" CREATOR_NAME_URL "\"\n");
#endif
if (opt_humminbirdext) {
+#if OLDGPX
gbfprintf(ofd, " xmlns:h=\"http://humminbird.com\"\n");
+#else
+ writer.writeAttribute("\n xmlns:h","http://humminbird.com");
+#endif
}
if (opt_garminext)
gbfprintf(ofd, " xmlns:gpxx=\"http://www.garmin.com/xmlschemas/GpxExtensions/v3\"\n"
" xmlns:gpxtpx=\"http://www.garmin.com/xmlschemas/TrackPointExtension/v1\"\n");
-#if OLD
+#if OLDGPX
gbfprintf(ofd, " xmlns=\"http://www.topografix.com/GPX/%c/%c\"\n", gpx_wversion[0], gpx_wversion[2]);
#else
writer.writeAttribute("\n xmlns", QString("http://www.topografix.com/GPX/%1/%2").arg(gpx_wversion[0]).arg(gpx_wversion[2]));
#endif
if (xsi_schema_loc) {
-#if OLD
+#if OLDGPX
gbfprintf(ofd, " xsi:schemaLocation=\"%s\">\n", xsi_schema_loc);
#else
writer.writeAttribute("\n xsi:schemaLocation", xsi_schema_loc);
#endif
} else {
-#if OLD
+#if OLDGPX
gbfprintf(ofd,
" xsi:schemaLocation=" DEFAULT_XSI_SCHEMA_LOC_FMT">\n",
gpx_wversion[0], gpx_wversion[2],
}
if (gpx_wversion_num > 10) {
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "<metadata>\n");
#else
writer.writeStartElement("metadata");
gpx_write_gdata(&gpx_global->url, "url");
gpx_write_gdata(&gpx_global->urlname, "urlname");
}
-#if OLD
+#if OLDGPX
xml_write_time(ofd, now, 0, "time");
#else
char time_string[64];
gpx_write_bounds();
if (gpx_wversion_num > 10) {
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "</metadata>\n");
#else
writer.writeEndElement();
gpx_route_pr();
gpx_reset_short_handle();
gpx_track_pr();
-#if OLD
+#if OLDGPX
gbfprintf(ofd, "</gpx>\n");
#else
writer.writeEndElement(); // Close gpx tag.